package com.aps.demo.controller;

import com.aps.common.entity.Result;
import com.aps.common.model.APSProductModel;
import com.aps.demo.engine.DataTransformationEngine;
import com.aps.demo.model.ProductionData;
import com.aps.demo.receiver.JSONDataReceiver;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * 参数模型控制器
 * 提供参数模型建立相关的REST API
 */
@Slf4j
@RestController
@RequestMapping("/api/parameter-model")
@Tag(name = "参数模型管理", description = "提供参数模型建立、验证和转换的API接口")
public class ParameterModelController {
    
    @Autowired
    private DataTransformationEngine transformationEngine;
    
    @Autowired
    private JSONDataReceiver jsonDataReceiver;
    
    /**
     * 从JSON文件建立参数模型
     */
    @PostMapping("/build-from-file")
    @Operation(summary = "从文件建立参数模型", description = "从指定的JSON文件读取生产数据并建立APS参数模型")
    public Result<APSProductModel> buildFromFile(
            @Parameter(description = "JSON文件路径", required = true) @RequestParam String filePath,
            @Parameter(description = "目标模型类型", example = "automotive") @RequestParam(defaultValue = "automotive") String targetModel) {
        
        try {
            log.info("从文件建立参数模型: {}, 目标模型: {}", filePath, targetModel);
            
            // 读取JSON数据
            ProductionData productionData = jsonDataReceiver.receiveFromFile(filePath);
            
            // 转换为APS参数模型
            APSProductModel model = transformationEngine.transform(productionData, targetModel);
            
            log.info("参数模型建立成功");
            return Result.success(model, "参数模型建立成功");
            
        } catch (Exception e) {
            log.error("参数模型建立失败", e);
            return Result.error("参数模型建立失败: " + e.getMessage());
        }
    }
    
    /**
     * 从JSON字符串建立参数模型
     */
    @PostMapping("/build-from-json")
    @Operation(summary = "从JSON字符串建立参数模型", description = "从JSON字符串数据建立APS参数模型")
    public Result<APSProductModel> buildFromJson(
            @Parameter(description = "JSON数据字符串", required = true) @RequestBody String jsonData,
            @Parameter(description = "目标模型类型", example = "automotive") @RequestParam(value = "targetModel", defaultValue = "automotive") String targetModel) {
        
        try {
            log.info("从JSON字符串建立参数模型，目标模型: {}", targetModel);
            
            // 读取JSON数据
            ProductionData productionData = jsonDataReceiver.receiveFromString(jsonData);
            
            // 转换为APS参数模型
            APSProductModel model = transformationEngine.transform(productionData, targetModel);
            
            log.info("参数模型建立成功");
            return Result.success(model, "参数模型建立成功");
            
        } catch (Exception e) {
            log.error("参数模型建立失败", e);
            return Result.error("参数模型建立失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取支持的适配器列表
     */
    @GetMapping("/adapters")
    @Operation(summary = "获取适配器列表", description = "获取系统支持的所有行业适配器")
    public Result<Map<String, String>> getAdapters() {
        Map<String, String> adapters = transformationEngine.getAdapters().entrySet().stream()
            .collect(java.util.stream.Collectors.toMap(
                Map.Entry::getKey,
                entry -> entry.getValue().getSupportedIndustry()
            ));
        
        return Result.success(adapters, "适配器列表获取成功");
    }
    
    /**
     * 验证生产数据
     */
    @PostMapping("/validate")
    @Operation(summary = "验证生产数据", description = "验证JSON格式的生产数据是否有效")
    public Result<Map<String, Object>> validateData(
            @Parameter(description = "待验证的JSON数据", required = true) @RequestBody String jsonData) {
        try {
            ProductionData productionData = jsonDataReceiver.receiveFromString(jsonData);
            JSONDataReceiver.ValidationResult result = jsonDataReceiver.validate(productionData);
            
            Map<String, Object> response = Map.of(
                "isValid", result.isValid(),
                "errors", result.getErrors()
            );
            
            return Result.success(response, "数据验证完成");
            
        } catch (Exception e) {
            log.error("数据验证失败", e);
            return Result.error("数据验证失败: " + e.getMessage());
        }
    }
    
    /**
     * 生成测试数据
     */
    @GetMapping("/generate-test-data")
    @Operation(summary = "生成测试数据", description = "生成各种场景的测试数据")
    public Result<Map<String, Object>> generateTestData(
            @Parameter(description = "测试场景类型", example = "basic") @RequestParam("scenario") String scenario) {
        try {
            log.info("生成测试数据，场景: {}", scenario);
            
            Map<String, Object> testData = generateTestDataByScenario(scenario);
            
            return Result.success(testData, "测试数据生成成功");
            
        } catch (Exception e) {
            log.error("测试数据生成失败", e);
            return Result.error("测试数据生成失败: " + e.getMessage());
        }
    }
    
    /**
     * 根据场景生成测试数据
     */
    private Map<String, Object> generateTestDataByScenario(String scenario) {
        Map<String, Object> data;
        
        switch (scenario.toLowerCase()) {
            case "basic":
                data = generateBasicTestData();
                break;
            case "small":
                data = generateSmallTestData();
                break;
            case "medium":
                data = generateMediumTestData();
                break;
            case "large":
                data = generateLargeTestData();
                break;
            case "urgent":
                data = generateUrgentTestData();
                break;
            case "resource_constrained":
                data = generateResourceConstrainedTestData();
                break;
            case "complex":
                data = generateComplexTestData();
                break;
            default:
                data = generateBasicTestData();
        }
        
        return data;
    }
    
    /**
     * 生成基础测试数据
     */
    private Map<String, Object> generateBasicTestData() {
        Map<String, Object> data = new HashMap<>();
        
        // 产品信息
        Map<String, Object> productInfo = new HashMap<>();
        productInfo.put("productId", "PROD-" + (int)(Math.random() * 1000));
        productInfo.put("productName", getRandomElement(new String[]{"汽车齿轮", "发动机零件", "刹车盘", "转向节", "减震器"}));
        productInfo.put("productCategory", getRandomElement(new String[]{"齿轮", "发动机", "制动", "转向", "悬挂"}));
        productInfo.put("material", getRandomElement(new String[]{"合金钢", "不锈钢", "碳钢", "铝合金", "铜合金"}));
        
        Map<String, Object> specifications = new HashMap<>();
        specifications.put("outerDiameter", createTimeValue(Math.random() * 100 + 10, "mm", "±0.1"));
        specifications.put("height", createTimeValue(Math.random() * 30 + 5, "mm", "±0.05"));
        specifications.put("weight", createTimeValue(Math.random() * 5 + 0.5, "kg", "±0.01"));
        productInfo.put("specifications", specifications);
        productInfo.put("annualDemand", (int)(Math.random() * 50000 + 10000));
        productInfo.put("description", "高精度产品，符合行业标准");
        
        data.put("productInfo", productInfo);
        
        // 订单
        List<Map<String, Object>> orders = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            Map<String, Object> order = new HashMap<>();
            order.put("orderId", "ORD-" + String.format("%03d", i + 1));
            order.put("customerName", getRandomElement(new String[]{"大众汽车", "宝马汽车", "奔驰汽车", "奥迪汽车", "丰田汽车"}));
            order.put("customerLevel", getRandomElement(new String[]{"A", "B", "C"}));
            order.put("productModel", "MODEL-" + (int)(Math.random() * 100));
            order.put("quantity", (int)(Math.random() * 1000 + 100));
            order.put("deliveryDate", getRandomFutureDate(7, 30));
            order.put("priority", getRandomElement(new String[]{"高", "中", "低"}));
            order.put("orderAmount", Math.random() * 100000 + 10000);
            orders.add(order);
        }
        data.put("orders", orders);
        
        // 工艺流程
        List<Map<String, Object>> processFlow = new ArrayList<>();
        String[] operations = {"车削加工", "铣削加工", "钻孔", "磨削", "热处理", "装配", "质检"};
        String[] equipmentTypes = {"车床", "铣床", "钻床", "磨床", "热处理炉", "装配线", "质检台"};
        
        for (int i = 0; i < 4; i++) {
            Map<String, Object> operation = new HashMap<>();
            operation.put("operationId", "STEP-" + String.format("%03d", i + 1));
            operation.put("operationName", operations[i % operations.length]);
            operation.put("sequence", i + 1);
            operation.put("equipmentType", equipmentTypes[i % equipmentTypes.length]);
            operation.put("standardTime", createTimeValue(Math.random() * 60 + 10, "分钟", ""));
            operation.put("setupTime", createTimeValue(Math.random() * 30 + 5, "分钟", ""));
            operation.put("personnelRequirement", getRandomElement(new String[]{"初级技工", "中级技工", "高级技工", "技师"}));
            operation.put("qualityRequirement", "标准质量要求");
            processFlow.add(operation);
        }
        data.put("processFlow", processFlow);
        
        // 设备
        List<Map<String, Object>> equipment = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            Map<String, Object> eq = new HashMap<>();
            eq.put("equipmentId", "EQ-" + String.format("%03d", i + 1));
            eq.put("equipmentName", equipmentTypes[i % equipmentTypes.length]);
            eq.put("equipmentType", equipmentTypes[i % equipmentTypes.length]);
            eq.put("dailyCapacity", createTimeValue(480.0, "分钟", ""));
            eq.put("efficiencyFactor", Math.random() * 0.2 + 0.8);
            eq.put("maintenanceSchedule", getRandomElement(new String[]{"每周维护", "每月维护", "每季度维护"}));
            eq.put("status", getRandomElement(new String[]{"正常", "维护中", "故障"}));
            equipment.add(eq);
        }
        data.put("equipment", equipment);
        
        // 人员
        List<Map<String, Object>> personnel = new ArrayList<>();
        String[] names = {"张三", "李四", "王五", "赵六", "钱七"};
        String[] jobTypes = {"车工", "铣工", "钻工", "磨工", "装配工", "质检员"};
        
        for (int i = 0; i < 3; i++) {
            Map<String, Object> person = new HashMap<>();
            person.put("personnelId", "PER-" + String.format("%03d", i + 1));
            person.put("name", names[i % names.length]);
            person.put("jobType", jobTypes[i % jobTypes.length]);
            person.put("skillLevel", getRandomElement(new String[]{"初级", "中级", "高级", "专家"}));
            person.put("dailyWorkHours", createTimeValue(8.0, "小时", ""));
            person.put("operableEquipment", Arrays.asList("EQ-" + String.format("%03d", i + 1)));
            person.put("status", getRandomElement(new String[]{"在岗", "休假", "培训"}));
            personnel.add(person);
        }
        data.put("personnel", personnel);
        
        // 约束条件
        Map<String, Object> constraints = new HashMap<>();
        List<Map<String, Object>> hardConstraints = new ArrayList<>();
        Map<String, Object> hardConstraint = new HashMap<>();
        hardConstraint.put("constraintId", "HC-001");
        hardConstraint.put("constraintType", "交期约束");
        hardConstraint.put("description", "订单必须在交付日期前完成");
        hardConstraint.put("priority", "高");
        hardConstraints.add(hardConstraint);
        constraints.put("hardConstraints", hardConstraints);
        
        List<Map<String, Object>> softConstraints = new ArrayList<>();
        Map<String, Object> softConstraint = new HashMap<>();
        softConstraint.put("constraintId", "SC-001");
        softConstraint.put("constraintType", "成本优化约束");
        softConstraint.put("description", "总成本不能超过预算");
        softConstraint.put("weight", Math.random() * 0.5 + 0.5);
        softConstraints.add(softConstraint);
        constraints.put("softConstraints", softConstraints);
        
        data.put("constraints", constraints);
        
        return data;
    }
    
    /**
     * 生成小规模测试数据
     */
    private Map<String, Object> generateSmallTestData() {
        Map<String, Object> data = generateBasicTestData();
        // 减少订单和工序数量
        ((List<?>) data.get("orders")).clear();
        ((List<?>) data.get("processFlow")).clear();
        ((List<?>) data.get("equipment")).clear();
        ((List<?>) data.get("personnel")).clear();
        
        // 添加少量数据
        addTestData(data, 2, 2, 2, 2);
        return data;
    }
    
    /**
     * 生成中等规模测试数据
     */
    private Map<String, Object> generateMediumTestData() {
        Map<String, Object> data = generateBasicTestData();
        // 清空基础数据
        ((List<?>) data.get("orders")).clear();
        ((List<?>) data.get("processFlow")).clear();
        ((List<?>) data.get("equipment")).clear();
        ((List<?>) data.get("personnel")).clear();
        
        // 添加中等规模数据
        addTestData(data, 8, 6, 6, 5);
        return data;
    }
    
    /**
     * 生成大规模测试数据
     */
    private Map<String, Object> generateLargeTestData() {
        Map<String, Object> data = generateBasicTestData();
        // 清空基础数据
        ((List<?>) data.get("orders")).clear();
        ((List<?>) data.get("processFlow")).clear();
        ((List<?>) data.get("equipment")).clear();
        ((List<?>) data.get("personnel")).clear();
        
        // 添加大规模数据
        addTestData(data, 15, 10, 10, 8);
        return data;
    }
    
    /**
     * 生成紧急交期测试数据
     */
    private Map<String, Object> generateUrgentTestData() {
        Map<String, Object> data = generateBasicTestData();
        // 修改订单交期为紧急
        List<Map<String, Object>> orders = (List<Map<String, Object>>) data.get("orders");
        for (Map<String, Object> order : orders) {
            order.put("deliveryDate", getRandomFutureDate(1, 3));
            order.put("priority", "高");
        }
        return data;
    }
    
    /**
     * 生成资源紧张测试数据
     */
    private Map<String, Object> generateResourceConstrainedTestData() {
        Map<String, Object> data = generateBasicTestData();
        // 减少资源数量
        List<Map<String, Object>> equipment = (List<Map<String, Object>>) data.get("equipment");
        List<Map<String, Object>> personnel = (List<Map<String, Object>>) data.get("personnel");
        
        if (equipment.size() > 1) equipment.remove(equipment.size() - 1);
        if (personnel.size() > 1) personnel.remove(personnel.size() - 1);
        
        return data;
    }
    
    /**
     * 生成复杂工艺测试数据
     */
    private Map<String, Object> generateComplexTestData() {
        Map<String, Object> data = generateBasicTestData();
        // 增加工序数量
        List<Map<String, Object>> processFlow = (List<Map<String, Object>>) data.get("processFlow");
        String[] operations = {"车削加工", "铣削加工", "钻孔", "磨削", "热处理", "装配", "质检", "包装", "清洗", "涂装"};
        String[] equipmentTypes = {"车床", "铣床", "钻床", "磨床", "热处理炉", "装配线", "质检台", "包装机", "清洗机", "涂装线"};
        
        for (int i = processFlow.size(); i < 8; i++) {
            Map<String, Object> operation = new HashMap<>();
            operation.put("operationId", "STEP-" + String.format("%03d", i + 1));
            operation.put("operationName", operations[i % operations.length]);
            operation.put("sequence", i + 1);
            operation.put("equipmentType", equipmentTypes[i % equipmentTypes.length]);
            operation.put("standardTime", createTimeValue(Math.random() * 60 + 10, "分钟", ""));
            operation.put("setupTime", createTimeValue(Math.random() * 30 + 5, "分钟", ""));
            operation.put("personnelRequirement", getRandomElement(new String[]{"初级技工", "中级技工", "高级技工", "技师"}));
            operation.put("qualityRequirement", "标准质量要求");
            processFlow.add(operation);
        }
        
        return data;
    }
    
    /**
     * 添加测试数据
     */
    private void addTestData(Map<String, Object> data, int orderCount, int operationCount, int equipmentCount, int personnelCount) {
        // 添加订单
        List<Map<String, Object>> orders = (List<Map<String, Object>>) data.get("orders");
        for (int i = orders.size(); i < orderCount; i++) {
            Map<String, Object> order = new HashMap<>();
            order.put("orderId", "ORD-" + String.format("%03d", i + 1));
            order.put("customerName", getRandomElement(new String[]{"大众汽车", "宝马汽车", "奔驰汽车", "奥迪汽车", "丰田汽车"}));
            order.put("customerLevel", getRandomElement(new String[]{"A", "B", "C"}));
            order.put("productModel", "MODEL-" + (int)(Math.random() * 100));
            order.put("quantity", (int)(Math.random() * 1000 + 100));
            order.put("deliveryDate", getRandomFutureDate(7, 30));
            order.put("priority", getRandomElement(new String[]{"高", "中", "低"}));
            order.put("orderAmount", Math.random() * 100000 + 10000);
            orders.add(order);
        }
        // 添加工序
        List<Map<String, Object>> processFlow = (List<Map<String, Object>>) data.get("processFlow");
        String[] operations = {"车削加工", "铣削加工", "钻孔", "磨削", "热处理", "装配", "质检"};
        String[] equipmentTypes = {"车床", "铣床", "钻床", "磨床", "热处理炉", "装配线", "质检台"};
        
        for (int i = processFlow.size(); i < operationCount; i++) {
            Map<String, Object> operation = new HashMap<>();
            operation.put("operationId", "STEP-" + String.format("%03d", i + 1));
            operation.put("operationName", operations[i % operations.length]);
            operation.put("sequence", i + 1);
            operation.put("equipmentType", equipmentTypes[i % equipmentTypes.length]);
            operation.put("standardTime", createTimeValue(Math.random() * 60 + 10, "分钟", ""));
            operation.put("setupTime", createTimeValue(Math.random() * 30 + 5, "分钟", ""));
            operation.put("personnelRequirement", getRandomElement(new String[]{"初级技工", "中级技工", "高级技工", "技师"}));
            operation.put("qualityRequirement", "标准质量要求");
            processFlow.add(operation);
        }
        
        // 添加设备
        List<Map<String, Object>> equipment = (List<Map<String, Object>>) data.get("equipment");
        for (int i = equipment.size(); i < equipmentCount; i++) {
            Map<String, Object> eq = new HashMap<>();
            eq.put("equipmentId", "EQ-" + String.format("%03d", i + 1));
            eq.put("equipmentName", equipmentTypes[i % equipmentTypes.length]);
            eq.put("equipmentType", equipmentTypes[i % equipmentTypes.length]);
            eq.put("dailyCapacity", createTimeValue(480.0, "分钟", ""));
            eq.put("efficiencyFactor", Math.random() * 0.2 + 0.8);
            eq.put("maintenanceSchedule", getRandomElement(new String[]{"每周维护", "每月维护", "每季度维护"}));
            eq.put("status", getRandomElement(new String[]{"正常", "维护中", "故障"}));
            equipment.add(eq);
        }
        
        // 添加人员
        List<Map<String, Object>> personnel = (List<Map<String, Object>>) data.get("personnel");
        String[] names = {"张三", "李四", "王五", "赵六", "钱七", "孙八", "周九", "吴十"};
        String[] jobTypes = {"车工", "铣工", "钻工", "磨工", "装配工", "质检员", "技师", "工程师"};
        
        for (int i = personnel.size(); i < personnelCount; i++) {
            Map<String, Object> person = new HashMap<>();
            person.put("personnelId", "PER-" + String.format("%03d", i + 1));
            person.put("name", names[i % names.length]);
            person.put("jobType", jobTypes[i % jobTypes.length]);
            person.put("skillLevel", getRandomElement(new String[]{"初级", "中级", "高级", "专家"}));
            person.put("dailyWorkHours", createTimeValue(8.0, "小时", ""));
            person.put("operableEquipment", Arrays.asList("EQ-" + String.format("%03d", (i % equipmentCount) + 1)));
            person.put("status", getRandomElement(new String[]{"在岗", "休假", "培训"}));
            personnel.add(person);
        }
    }
    
    /**
     * 创建时间值对象
     */
    private Map<String, Object> createTimeValue(double value, String unit, String tolerance) {
        Map<String, Object> timeValue = new HashMap<>();
        timeValue.put("value", value);
        timeValue.put("unit", unit);
        if (!tolerance.isEmpty()) {
            timeValue.put("tolerance", tolerance);
        }
        return timeValue;
    }
    
    /**
     * 获取随机元素
     */
    private String getRandomElement(String[] array) {
        return array[(int)(Math.random() * array.length)];
    }
    
    /**
     * 获取随机未来日期
     */
    private String getRandomFutureDate(int minDays, int maxDays) {
        java.time.LocalDate today = java.time.LocalDate.now();
        int days = (int)(Math.random() * (maxDays - minDays + 1)) + minDays;
        return today.plusDays(days).format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd"));
    }
} 